tinkit 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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