tinkit 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +176 -0
  2. data/README +11 -0
  3. data/Rakefile +75 -0
  4. data/lib/glue_envs/couchrest/couchrest_attachment_handler.rb +260 -0
  5. data/lib/glue_envs/couchrest/couchrest_files_mgr.rb +198 -0
  6. data/lib/glue_envs/couchrest_glue_env.rb +536 -0
  7. data/lib/glue_envs/files_mgr_base.rb +51 -0
  8. data/lib/glue_envs/filesystem/filesystem_files_mgr.rb +187 -0
  9. data/lib/glue_envs/filesystem_glue_env.rb +395 -0
  10. data/lib/glue_envs/mysql/mysql_files_mgr.rb +175 -0
  11. data/lib/glue_envs/mysql_glue_env.rb +428 -0
  12. data/lib/glue_envs/sdb_s3/sdb_s3_files_mgr.rb +314 -0
  13. data/lib/glue_envs/sdb_s3_glue_env.rb +248 -0
  14. data/lib/helpers/camel.rb +21 -0
  15. data/lib/helpers/filesystem_helpers.rb +27 -0
  16. data/lib/helpers/hash_helpers.rb +74 -0
  17. data/lib/helpers/log_helper.rb +34 -0
  18. data/lib/helpers/mime_types_new.rb +126 -0
  19. data/lib/helpers/old_more_open_struct.rb +28 -0
  20. data/lib/helpers/require_helper.rb +45 -0
  21. data/lib/helpers/tk_escape.rb +17 -0
  22. data/lib/midas/bufs_data_structure.rb +84 -0
  23. data/lib/midas/node_element_operations.rb +264 -0
  24. data/lib/tinkit.rb +38 -0
  25. data/lib/tinkit_base_node.rb +733 -0
  26. data/lib/tinkit_node_factory.rb +47 -0
  27. data/spec/couchrest_files_mgr_spec.rb +551 -0
  28. data/spec/couchrest_glue_spec.rb +246 -0
  29. data/spec/filesystem_files_mgr_spec.rb +236 -0
  30. data/spec/filesystem_glue_spec.rb +243 -0
  31. data/spec/filesystem_helpers_spec.rb +42 -0
  32. data/spec/helpers/bufs_node_builder.rb +17 -0
  33. data/spec/helpers/bufs_sample_dataset.rb +160 -0
  34. data/spec/helpers/bufs_test_environments.rb +81 -0
  35. data/spec/helpers/tmp_view_cleaner.rb +15 -0
  36. data/spec/lib_helpers/tk_escape_spec.rb +45 -0
  37. data/spec/mysql_files_mgr_spec.rb +250 -0
  38. data/spec/mysql_glue_spec.rb +214 -0
  39. data/spec/node_element_operations_spec.rb +392 -0
  40. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec1.rb +82 -0
  41. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec2.rb +68 -0
  42. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec3.rb +80 -0
  43. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec4.rb +110 -0
  44. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec5.rb +84 -0
  45. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec6.rb +83 -0
  46. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec7.rb +101 -0
  47. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec8.rb +92 -0
  48. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec_all.rb +266 -0
  49. data/spec/sdb_s3_glue_spec.rb +230 -0
  50. data/spec/tinkit_node_factory_spec.rb +1108 -0
  51. metadata +114 -0
@@ -0,0 +1,47 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.dirname(__FILE__), '/helpers/require_helper')
3
+
4
+ require Tinkit.lib 'tinkit_base_node'
5
+ require Tinkit.helpers 'log_helper'
6
+
7
+ class TinkitNodeFactory
8
+ #Set Logger
9
+ @@log = TinkitLog.set(self.name, :debug)
10
+
11
+ def self.make(node_env)
12
+ TinkitLog.log_raise "No Node Environment provided" unless node_env
13
+ TinkitLog.log_raise "Empty Node Environment provided" if node_env.empty?
14
+ TinkitLog.log_raise "Malformed Node Environment" unless node_env.respond_to?(:keys)
15
+ TinkitLog.log_raise "Malformed Node Environment" unless node_env.keys.include? :persist_model
16
+
17
+
18
+ neo_env = node_env[:data_model] || {}
19
+
20
+ neo = NodeElementOperations.new(neo_env)
21
+ data_model_bindings = {:key_fields => neo.key_fields,
22
+ #:data_ops_set => neo.field_op_set_sym,
23
+ :views => neo.views}
24
+
25
+ #TODO: Make setting the environment thread safe
26
+ class_environment = node_env[:persist_model]
27
+ user_doc_class_name = node_env[:node_class_id]
28
+
29
+ #Security TODO: remove spaces and other
30
+
31
+ #---- Dynamic Class Definitions ----
32
+ dyn_user_class_def = "class #{user_doc_class_name} < TinkitBaseNode
33
+
34
+ class << self; attr_accessor :user_attachClass, end
35
+
36
+ end"
37
+
38
+ TinkitNodeFactory.class_eval(dyn_user_class_def)
39
+ docClass = TinkitNodeFactory.const_get(user_doc_class_name)
40
+
41
+ docClass.data_struc = neo
42
+
43
+ #TODO: Streamline the paramaters (maybe one env paramater?)
44
+ docClass.set_environment(class_environment, data_model_bindings)
45
+ docClass
46
+ end
47
+ end
@@ -0,0 +1,551 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/helpers/require_helper')
3
+
4
+ require 'spec'
5
+ require 'couchrest'
6
+
7
+ require Tinkit.glue 'couchrest/couchrest_files_mgr'
8
+
9
+ include CouchrestInterface
10
+
11
+ FileMgrTestDb = CouchRest.database!("http://127.0.0.1:5984/couchrest_file_mgr_test")
12
+ FileMgrTestDb.compact!
13
+
14
+ GlueEnvMock = Struct.new(:model_key, :user_id, :moab_data)
15
+
16
+ class MockAttachClass < CouchrestAttachment
17
+ use_database FileMgrTestDb
18
+
19
+ def self.namespace
20
+ FileMgrTestDb
21
+ end
22
+ end
23
+
24
+ class MockNode
25
+ attr_accessor :_id, :my_GlueEnv, :_model_metadata, :attachment_doc_id
26
+
27
+ def initialize(id, glue_env, model_md)
28
+ @_id = id
29
+ @my_GlueEnv = glue_env
30
+ @_model_metadata = model_md
31
+ @atts = {}
32
+ end
33
+
34
+ def __set_userdata_key(node_att_doc_id, db_att_doc_id)
35
+ @attachment_doc_id = db_att_doc_id
36
+ end
37
+
38
+ end
39
+
40
+ describe FilesMgr, "Setup and intialization" do
41
+
42
+ before(:all) do
43
+ moab_data = {:attachClass => MockAttachClass, :db => FileMgrTestDb }
44
+ @glue_env_mock = GlueEnvMock.new("_id", "couchrest_user", moab_data)
45
+ @node_key = :_id
46
+
47
+ file1_data = "Example File1\nJust some text"
48
+ file2_data = "Example File2\nJust some more text"
49
+ file1_fname = "/tmp/example_file1.txt"
50
+ file2_fname = "/tmp/example_file2.txt"
51
+ files = {file1_fname => file1_data, file2_fname => file2_data}
52
+ files.each do |fname, data|
53
+ File.open(fname, 'w'){|f| f.write(data)}
54
+ end
55
+ @file_datas = [{:src_filename => file1_fname}, {:src_filename => file2_fname}]
56
+ @node1_data = {:_id => 'spec_test1', :data => 'stuff1'}
57
+ end
58
+
59
+ it "should initialize" do
60
+ node_key_value = @node1_data[@node_key]
61
+ attach_handler = FilesMgr.new(@glue_env_mock, node_key_value)
62
+ att_class_base_name = "MoabAttachmentHandler"
63
+ user_id = @glue_env_mock.user_id
64
+ attach_handler.attachment_doc_class.should == @glue_env_mock.moab_data[:attachClass]
65
+ end
66
+ end
67
+
68
+ describe FilesMgr, "Basic Operations" do
69
+ before(:all) do
70
+ #@user_datastore_location = "/tmp/datastore_location"
71
+ @file1_fname = "/tmp/example_file1.txt"
72
+ @file2_fname = "/tmp/example_file2.txt"
73
+ f1_bname = File.basename(@file1_fname)
74
+ f2_bname = File.basename(@file2_fname)
75
+ @file_stored_data = { f1_bname => File.open(@file1_fname, 'rb'){|f| f.read},
76
+ f2_bname =>File.open(@file2_fname, 'rb'){|f| f.read} }
77
+
78
+ @mock_key = :_id
79
+ #@nodeMockClass = Struct.new(@mock_key, :my_GlueEnv, :"_model_metadata")
80
+
81
+ moab_data = {:attachClass => MockAttachClass, :db => FileMgrTestDb }
82
+ @glue_env_mock = GlueEnvMock.new(@mock_key,
83
+ "couchrest_user", moab_data)
84
+
85
+ @file_datas = [{:src_filename => @file1_fname}, {:src_filename => @file2_fname}]
86
+ end
87
+
88
+
89
+ before(:each) do
90
+ @node1_data = {:_id => 'spec_test1', :data => 'stuff1'}
91
+ model_metadata = {:_id => 'spec_test1'}
92
+ @node_mock = MockNode.new(@node1_data[@mock_key],
93
+ @glue_env_mock,
94
+ model_metadata)
95
+
96
+ node_key_value = @node1_data[@mock_key]
97
+ @attach_handler = FilesMgr.new(@glue_env_mock, node_key_value)
98
+ #@attach_handler.subtract_files(nil, :all)
99
+ end
100
+
101
+ after(:all) do
102
+ FileMgrTestDb.delete!
103
+ end
104
+
105
+ it "should add and retrieve files" do
106
+ node = @node_mock
107
+
108
+ @file_datas.each do |file_data|
109
+ file_basename = File.basename(file_data[:src_filename])
110
+ data = @attach_handler.get_raw_data(node, file_basename)
111
+ data.should be_nil
112
+ end
113
+
114
+ #Add the Files
115
+ @attach_handler.add(node, @file_datas)
116
+
117
+ #Get the files and verify data
118
+ @file_datas.each do |file_data|
119
+ file_basename = File.basename(file_data[:src_filename])
120
+ data = @attach_handler.get_raw_data(node, file_basename)
121
+ data.should == @file_stored_data[file_basename]
122
+ end
123
+ end
124
+
125
+ it "should list attachment files" do
126
+ files = @attach_handler.list(@node_mock)
127
+ files.sort.should == @file_stored_data.keys.sort
128
+ end
129
+
130
+ it "should list metadata" do
131
+ md = @attach_handler.get_attachments_metadata(@node_mock)
132
+ md.should_not == nil
133
+ @file_datas.each do |file_data|
134
+ file_basename = File.basename(file_data[:src_filename])
135
+ each_md = md[file_basename]
136
+ each_md.should_not == nil
137
+ each_md.keys.should include :content_type
138
+ each_md.keys.should include :file_modified
139
+
140
+ file_basename = File.basename(file_data[:src_filename])
141
+ md[file_basename][:content_type].should =~ /^text\/plain/
142
+ time_str = md[file_basename][:file_modified]
143
+ Time.parse(time_str).should >= Time.now - 2 #should have been modified less than 2 seconds ago
144
+ end
145
+ end
146
+
147
+ it "should be well behaved adding more files" do
148
+ node = @node_mock
149
+
150
+ #Get the original files and verify data
151
+ @file_datas.each do |file_data|
152
+ file_basename = File.basename(file_data[:src_filename])
153
+ data = @attach_handler.get_raw_data(node, file_basename)
154
+ data.should == @file_stored_data[file_basename]
155
+ end
156
+
157
+ #create some more files
158
+ file1_data = "Example File1\nNEW!! text"
159
+ file3_data = "Example File3\nYet more text"
160
+ file4_data = "Example File4\nand more text"
161
+ file3_fname = "/tmp/example_file3.txt"
162
+ file4_fname = "/tmp/example_file4.txt"
163
+ files = {@file1_fname => file1_data, file3_fname => file3_data, file4_fname => file4_data}
164
+ files.each do |fname, data|
165
+ File.open(fname, 'w'){|f| f.write(data)}
166
+ end
167
+ file1_data.should == File.open(@file1_fname){|f| f.read}
168
+
169
+ @file_datas2 = [{:src_filename => @file1_fname},
170
+ {:src_filename => file3_fname},
171
+ {:src_filename => file4_fname}]
172
+
173
+
174
+ #add them
175
+ @attach_handler.add(node, @file_datas2)
176
+
177
+ #Check the unchanged file (file2)
178
+ file2_basename = File.basename(@file2_fname)
179
+ data2 = @attach_handler.get_raw_data(node, file2_basename)
180
+ data2.should == @file_stored_data[file2_basename]
181
+
182
+ #Get the changed files and verify it is the new data
183
+ file1_basename = File.basename(@file1_fname)
184
+ data1 = @attach_handler.get_raw_data(node, file1_basename)
185
+ data1.should == file1_data
186
+
187
+ file3_basename = File.basename(file3_fname)
188
+ data3 = @attach_handler.get_raw_data(node, file3_basename)
189
+ data3.should == file3_data
190
+
191
+ file4_basename = File.basename(file4_fname)
192
+ data4 = @attach_handler.get_raw_data(node, file4_basename)
193
+ data4.should == file4_data
194
+ end
195
+
196
+ it "should delete (subtract) files" do
197
+ node = @node_mock
198
+ files_to_delete = [@file1_fname, @file2_fname]
199
+ #they should exist in the node
200
+ files_to_delete.each do |fname|
201
+ file_basename = File.basename(fname)
202
+ data = @attach_handler.get_raw_data(node, file_basename)
203
+ data.should match /^Example File/
204
+ end
205
+
206
+ basenames_to_delete = files_to_delete.map{|f| File.basename(f)}
207
+ @attach_handler.subtract(node, basenames_to_delete)
208
+
209
+ files_to_delete.each do |fname|
210
+ file_basename = File.basename(fname)
211
+ data = @attach_handler.get_raw_data(node, file_basename)
212
+ data.should be_nil
213
+ end
214
+ end
215
+
216
+ it "should add attachments from the raw data" do
217
+ node = @node_mock
218
+
219
+ raw_data = "Example File3\nYet more text"
220
+ content_type = "text/plain"
221
+ modified_at = Time.now.to_s
222
+ att_name = "example_raw_data.txt"
223
+
224
+ #Add the Raw Data
225
+ @attach_handler.add_raw_data(node, att_name, content_type, raw_data, modified_at)
226
+
227
+ #Get the files and verify data
228
+
229
+ data = @attach_handler.get_raw_data(node, att_name)
230
+ md = @attach_handler.get_attachments_metadata(node)[att_name]
231
+
232
+ data.should == raw_data
233
+ md[:content_type].should == content_type
234
+ md[:file_modified].should == modified_at
235
+ end
236
+
237
+ it "should delete all (subtract_all) files" do
238
+ node = @node_mock
239
+
240
+ #create some more attachments
241
+ del_data = {}
242
+ del_data["del_data1"] = "my life will be short"
243
+ del_data["del_data2"] = "alas too short"
244
+
245
+ #add the attachments
246
+ del_data.each do |name, data|
247
+ @attach_handler.add_raw_data(node, name, "text/plain", data, Time.now.to_s)
248
+ end
249
+
250
+ #verify it's there
251
+ del_data.each do |name, data|
252
+ stored_data = @attach_handler.get_raw_data(node, name)
253
+ stored_data.should == data
254
+ end
255
+
256
+ #delete it all
257
+ @attach_handler.subtract(node, :all)
258
+
259
+ #verify it's not there
260
+ del_data.each do |name, data|
261
+ stored_data = @attach_handler.get_raw_data(node, name)
262
+ stored_data.should be_nil
263
+ end
264
+ end
265
+
266
+ end
267
+ =begin
268
+ it "should create object and update the database with a single attachment if there is no other doc in database" do
269
+ #set initial conditions
270
+ test_file = @test_files['binary_data_pptx']
271
+ test_file_basename = File.basename(test_file)
272
+ test_file_modified_time = File.mtime(test_file)
273
+ test_doc = @test_doc
274
+ test_doc_id = @test_doc_id
275
+ md_params = {}
276
+ md_params['content_type'] = MimeNew.for_ofc_x(test_file)
277
+ md_params['file_modified'] = test_file_modified_time.to_s
278
+ data = File.open(test_file, 'rb') {|f| f.read}
279
+ attachs = {test_file_basename => {'data' => data, 'md' => md_params }}
280
+ #test
281
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, CouchrestAttachment, attachs )
282
+ #check results
283
+
284
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
285
+ bia['_id'].should == test_attachment_id
286
+ #test_doc.attachment_doc_id.should == test_attachment_id
287
+ #p bia.class
288
+ #Note the lack of escaping on the file name, this only works
289
+ #because the original file name did not need escaping
290
+ bia['md_attachments'][test_file_basename]['file_modified'].should == test_file_modified_time.to_s
291
+ bia['_attachments'][test_file_basename]['content_type'].should == md_params['content_type']
292
+ end
293
+
294
+
295
+ it "should handle file names with strange (but somewhat common) characters and convert to more standard form" do
296
+ test_file = @test_files['strange_characters_in_file_name']
297
+ test_file_basename = File.basename(test_file)
298
+ test_file_modified_time = File.mtime(test_file)
299
+ test_doc = @test_doc
300
+ test_doc_id = @test_doc_id
301
+ #test_doc_id = 'dummy_doc_strange_character_file_name'
302
+ md_params = {}
303
+ md_params['content_type'] = MimeNew.for_ofc_x(test_file)
304
+ md_params['file_modified'] = test_file_modified_time.to_s
305
+ data = File.open(test_file, 'rb') {|f| f.read}
306
+ attachs = {test_file_basename => {'data' => data, 'md' => md_params }}
307
+ #test
308
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, CouchrestAttachment, attachs )
309
+ #check results
310
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
311
+ bia['_id'].should == test_attachment_id
312
+ bia['md_attachments'][TkEscape.escape(test_file_basename)]['file_modified'].should == test_file_modified_time.to_s
313
+ bia['_attachments'][TkEscape.escape(test_file_basename)]['content_type'].should == md_params['content_type']
314
+ end
315
+
316
+ it "should create multiple attachments in one update" do
317
+ #set initial conditions
318
+ test_file1 = @test_files['binary_data2_docx']
319
+ test_file2 = @test_files['simple_text_file']
320
+ test_file1_basename = File.basename(test_file1)
321
+ test_file2_basename = File.basename(test_file2)
322
+ md_params1 = {}
323
+ md_params2 = {}
324
+ md_params1['content_type'] = MimeNew.for_ofc_x(test_file1)
325
+ md_params2['content_type'] = MimeNew.for_ofc_x(test_file2)
326
+ md_params1['file_modified'] = File.mtime(test_file1).to_s
327
+ md_params2['file_modified'] = File.mtime(test_file2).to_s
328
+ data1 = File.open(test_file1, 'rb') {|f| f.read}
329
+ data2 = File.open(test_file2, 'rb') {|f| f.read}
330
+ attachs = { test_file1_basename => {'data' => data1, 'md' => md_params1},
331
+ test_file2_basename => {'data' => data2, 'md' => md_params2}
332
+ }
333
+ test_doc = @test_doc
334
+ test_doc_id = @test_doc_id
335
+ #test_doc_id = 'dummy_create_multiple_attachments'
336
+ #test
337
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, ::CouchrestAttachment, attachs )
338
+ #verify results
339
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
340
+ bia['_id'].should == test_attachment_id
341
+ bia['md_attachments'][TkEscape.escape(test_file1_basename)]['file_modified'].should == File.mtime(test_file1).to_s
342
+ bia['_attachments'][TkEscape.escape(test_file1_basename)]['content_type'].should == md_params1['content_type']
343
+ bia['md_attachments'][TkEscape.escape(test_file2_basename)]['file_modified'].should == File.mtime(test_file2).to_s
344
+ bia['_attachments'][TkEscape.escape(test_file2_basename)]['content_type'].should == md_params2['content_type']
345
+ end
346
+
347
+ it "should add new files to an existing attachment doc" do
348
+ #set initial conditions existing attachment
349
+ test_file1 = @test_files['binary_data2_docx']
350
+ test_file2 = @test_files['simple_text_file']
351
+ test_file1_basename = File.basename(test_file1)
352
+ test_file2_basename = File.basename(test_file2)
353
+ md_params1 = {}
354
+ md_params2 = {}
355
+ md_params1['content_type'] = MimeNew.for_ofc_x(test_file1)
356
+ md_params2['content_type'] = MimeNew.for_ofc_x(test_file2)
357
+ md_params1['file_modified'] = File.mtime(test_file1).to_s
358
+ md_params2['file_modified'] = File.mtime(test_file2).to_s
359
+ data1 = File.open(test_file1, 'rb') {|f| f.read}
360
+ data2 = File.open(test_file2, 'rb') {|f| f.read}
361
+ attachs = { test_file1_basename => {'data' => data1, 'md' => md_params1},
362
+ test_file2_basename => {'data' => data2, 'md' => md_params2}
363
+ }
364
+ #test_doc_id = 'dummy_add_new_attachments'
365
+ test_doc = @test_doc
366
+ test_doc_id = @test_doc_id
367
+ bia_existing = CouchrestAttachment.add_attachment_package(test_doc_id, ::CouchrestAttachment, attachs )
368
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
369
+ #verify attachment exists
370
+ bia_existing['_id'].should == test_attachment_id
371
+ #set initial conditions for test file
372
+ test_file = @test_files['simple_text_file2']
373
+ test_file_modified_time = File.mtime(test_file)
374
+ test_file_basename = File.basename(test_file)
375
+ md_params = {}
376
+ md_params['content_type'] = MimeNew.for_ofc_x(test_file)
377
+ md_params['file_modified'] = test_file_modified_time.to_s
378
+ data = File.open(test_file, 'rb') {|f| f.read}
379
+ attachs = {test_file_basename => {'data' => data, 'md' => md_params }}
380
+ bia_existing = CouchrestAttachment.get(bia_existing['_id'])
381
+ #test
382
+ bia_updated = bia_existing.class.update_attachment_package(bia_existing, attachs )
383
+ #verify results
384
+ #p test_file_basename
385
+ #p TkEscape.escape(test_file_basename)
386
+ bia_updated['_id'].should == bia_existing['_id']
387
+ bia_updated['md_attachments'][TkEscape.escape(test_file_basename)]['file_modified'].should == test_file_modified_time.to_s
388
+ bia_updated['_attachments'][TkEscape.escape(test_file_basename)]['content_type'].should == md_params['content_type']
389
+ end
390
+
391
+ it "should replace older attachment data with new ones, but not vice versa" do
392
+ #set initial conditions
393
+ test_file = @test_files['simple_text_file']
394
+ test_file_basename = File.basename(test_file)
395
+ test_file_modified_time = File.mtime(test_file)
396
+ test_doc = @test_doc
397
+ test_doc_id = @test_doc_id
398
+ #test_doc_id = 'dummy_fresh_attachment_replaces_stale'
399
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
400
+ #create a single record
401
+ md_params = {}
402
+ md_params['content_type'] = MimeNew.for_ofc_x(test_file)
403
+ md_params['file_modified'] = test_file_modified_time.to_s
404
+ data = File.open(test_file, 'rb') {|f| f.read}
405
+ attachs = {test_file_basename => {'data' => data, 'md' => md_params }}
406
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, CouchrestAttachment, attachs )
407
+ #verify initial condition
408
+ bia['_id'].should == test_attachment_id
409
+ bia['md_attachments'][TkEscape.escape(test_file_basename)]['file_modified'].should == test_file_modified_time.to_s
410
+ bia['_attachments'][TkEscape.escape(test_file_basename)]['content_type'].should == md_params['content_type']
411
+
412
+ #set initial conditions for fresh and stale file
413
+ stale_file = @test_files['stale_file']
414
+ fresh_file = @test_files['fresh_file']
415
+ stale_basename = File.basename(stale_file)
416
+ fresh_basename = File.basename(fresh_file)
417
+ stale_modified_time = File.mtime(stale_file)
418
+ fresh_modified_time = File.mtime(fresh_file)
419
+ md_params_stale = {}
420
+ md_params_fresh = {}
421
+ md_params_stale['content_type'] = MimeNew.for_ofc_x(stale_file)
422
+ md_params_fresh['content_type'] = MimeNew.for_ofc_x(fresh_file)
423
+ md_params_stale['file_modified'] = stale_modified_time.to_s
424
+ md_params_fresh['file_modified'] = fresh_modified_time.to_s
425
+ stale_data = File.open(stale_file, 'rb') {|f| f.read}
426
+ fresh_data = File.open(fresh_file, 'rb') {|f| f.read}
427
+ attachs = {stale_basename => {'data' => stale_data, 'md' => md_params_stale},
428
+ fresh_basename => {'data' => fresh_data, 'md' => md_params_fresh}
429
+ }
430
+
431
+ #for creating, use the sid and the method create_.... for updateing, use the sia and the method update...
432
+ bia_updated = CouchrestAttachment.update_attachment_package(bia, attachs )
433
+ #verify initial conditions
434
+ bia_updated['_id'].should == test_attachment_id
435
+ bia_updated['md_attachments'][TkEscape.escape(stale_basename)]['file_modified'].should == stale_modified_time.to_s
436
+ bia_updated['_attachments'][TkEscape.escape(stale_basename)]['content_type'].should == md_params_stale['content_type']
437
+ bia_updated['md_attachments'][TkEscape.escape(fresh_basename)]['file_modified'].should == fresh_modified_time.to_s
438
+ bia_updated['_attachments'][TkEscape.escape(fresh_basename)]['content_type'].should == md_params_fresh['content_type']
439
+ #if the above tests pass, then the files and database are synchronized
440
+
441
+ sleep 1 #to put some time difference
442
+
443
+ unstale_data = stale_data + "\n This data is only for the database"
444
+ unstale_modified_time = Time.now.to_s
445
+ #puts "Unstale Mod Time (db is more recent): #{unstale_modified_time}"
446
+ unstale_content_type = 'text/plain;unstale'
447
+ unstale_params = {'file_modified' => unstale_modified_time, 'content_type' => unstale_content_type}
448
+ unstale_attach = { TkEscape.escape(stale_basename) => {'data' => unstale_data, 'md'=> unstale_params } }
449
+
450
+ CouchrestAttachment.update_attachment_package(bia, unstale_attach)
451
+ #database should now have more recent information for @stale_basename
452
+
453
+ sleep 1 #to put some time difference
454
+ #puts "Fresh File Mod Time (file is more recent): #{File.mtime(@fresh_file)}"
455
+
456
+ File.open(fresh_file, 'a'){|f| f.write("\n This data is only for the file")}
457
+ #puts "Fresh File Mod Time (file is more recent): #{File.mtime(@fresh_file)}"
458
+ #file should now have more recent information for @fresh_basename
459
+
460
+ #try and update again with both files
461
+ md_params_stale2 = {}
462
+ md_params_fresh2 = {}
463
+ md_params_stale2['content_type'] = MimeNew.for_ofc_x(stale_file)
464
+ fresh_content_type = 'text/plain;fresh'
465
+ md_params_fresh2['content_type'] = fresh_content_type #MimeNew.for_ofc_x(@fresh_file)
466
+ md_params_stale2['file_modified'] = File.mtime(stale_file).to_s
467
+ fresh_modified_time = File.mtime(fresh_file).to_s
468
+ md_params_fresh2['file_modified'] = fresh_modified_time
469
+ stale_data2 = File.open(stale_file, 'rb') {|f| f.read}
470
+ fresh_data2 = File.open(fresh_file, 'rb') {|f| f.read}
471
+ attachs = {TkEscape.escape(stale_basename) => {'data' => stale_data2, 'md' => md_params_stale2},
472
+ TkEscape.escape(fresh_basename) => {'data' => fresh_data2, 'md' => md_params_fresh2}
473
+ }
474
+ #test
475
+ new_bia = CouchrestAttachment.get(bia['_id'])
476
+ fresh_bia = CouchrestAttachment.update_attachment_package(new_bia, attachs )
477
+
478
+ #verify results
479
+ #db should have fresh file, but not stale one (and maintain older db attachment)
480
+ fresh_bia['_id'].should == test_attachment_id
481
+ fresh_bia['md_attachments'][TkEscape.escape(stale_basename)]['file_modified'].should == unstale_modified_time
482
+ fresh_bia['_attachments'][TkEscape.escape(stale_basename)]['content_type'].should == unstale_content_type
483
+ fresh_bia['md_attachments'][TkEscape.escape(fresh_basename)]['file_modified'].should == fresh_modified_time
484
+ fresh_bia['_attachments'][TkEscape.escape(fresh_basename)]['content_type'].should == fresh_content_type
485
+ end
486
+
487
+ it "should combine all attachment metadata when it is retrieved" do
488
+ #set initial conditions
489
+ test_file1 = @test_files['binary_data2_docx']
490
+ test_file2 = @test_files['simple_text_file']
491
+ test_file1_basename = File.basename(test_file1)
492
+ test_file2_basename = File.basename(test_file2)
493
+ test_file1_modified_time = File.mtime(test_file1)
494
+ test_file2_modified_time = File.mtime(test_file2)
495
+ md_params1 = {}
496
+ md_params2 = {}
497
+ md_params1['content_type'] = MimeNew.for_ofc_x(test_file1)
498
+ md_params2['content_type'] = MimeNew.for_ofc_x(test_file2)
499
+ md_params1['file_modified'] = test_file1_modified_time.to_s
500
+ md_params2['file_modified'] = test_file2_modified_time.to_s
501
+ data1 = File.open(test_file1, 'rb') {|f| f.read}
502
+ data2 = File.open(test_file2, 'rb') {|f| f.read}
503
+ attachs = {test_file1_basename => {'data' => data1, 'md' => md_params1},
504
+ test_file2_basename => {'data' => data2, 'md' => md_params2}
505
+ }
506
+ test_doc = @test_doc
507
+ test_doc_id = test_doc._model_metadata[:_id]
508
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
509
+ test_attachment = CouchrestAttachment.get(test_attachment_id)
510
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, CouchrestAttachment, attachs )
511
+ data = CouchrestAttachment.get_attachments(bia)
512
+ #puts "SIA data: #{data.inspect}"
513
+ data[TkEscape.escape(test_file1_basename)]['file_modified'].should == test_file1_modified_time.to_s
514
+ data[TkEscape.escape(test_file1_basename)]['content_type'].should == MimeNew.for_ofc_x(test_file1)
515
+ end
516
+
517
+ it "should delete attachments" do
518
+ #set initial conditions
519
+ test_file1 = @test_files['binary_data2_docx']
520
+ test_file2 = @test_files['simple_text_file']
521
+ test_file1_basename = File.basename(test_file1)
522
+ test_file2_basename = File.basename(test_file2)
523
+ test_file1_modified_time = File.mtime(test_file1)
524
+ test_file2_modified_time = File.mtime(test_file2)
525
+ md_params1 = {}
526
+ md_params2 = {}
527
+ md_params1['content_type'] = MimeNew.for_ofc_x(test_file1)
528
+ md_params2['content_type'] = MimeNew.for_ofc_x(test_file2)
529
+ md_params1['file_modified'] = test_file1_modified_time.to_s
530
+ md_params2['file_modified'] = test_file2_modified_time.to_s
531
+ data1 = File.open(test_file1, 'rb') {|f| f.read}
532
+ data2 = File.open(test_file2, 'rb') {|f| f.read}
533
+ attachs = {test_file1_basename => {'data' => data1, 'md' => md_params1},
534
+ test_file2_basename => {'data' => data2, 'md' => md_params2}
535
+ }
536
+ test_doc = @test_doc
537
+ test_doc_id = test_doc._model_metadata[:_id]
538
+ test_attachment_id = test_doc_id + CouchrestAttachment::AttachmentID
539
+ test_attachment = CouchrestAttachment.get(test_attachment_id)
540
+ bia = CouchrestAttachment.add_attachment_package(test_doc_id, CouchrestAttachment, attachs )
541
+ #test
542
+ bia.remove_attachment(test_file1_basename)
543
+ #verify
544
+ new_atts = bia.get_attachments
545
+ #puts "Should be only 1: #{new_atts.keys.inspect}"
546
+ new_atts.keys.size.should == 1
547
+ new_atts.keys.first.should == TkEscape.escape(test_file2_basename)
548
+
549
+ end
550
+ end
551
+ =end