fs_attachable 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b8f5b00ebbe7a812434530c24783474f2605546a284d23e15e36f673c9b33c82
4
+ data.tar.gz: 15815d5a9f5131509d8e875f554037dbb850d20da3ade68f51a62f5f54ddd8ac
5
+ SHA512:
6
+ metadata.gz: 2a17180780a64f974856c4e910757fc0525074702f193b73a4c0fc8714cefa27c17c4ec86eb30e41f92fff26c2da8597009630e3ba242171031aa5de9cedf6b8
7
+ data.tar.gz: 3c91dd1effe33f83de9e6bc064e44de0c0414f7cc10bd17184d13e5982dd79af4c816a5807f05868cd7ea82fcfa5ccbeb3435f84cfaa40aeef5d5eb2da253c11
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # FsAttachable
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/fs_attachable`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/fs_attachable.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+ require 'release/gem'
@@ -0,0 +1,59 @@
1
+
2
+ require 'singleton'
3
+ require 'fileutils'
4
+
5
+ module FsAttachable
6
+
7
+ class ConfigError < StandardError; end
8
+
9
+ class ConfigDomain
10
+ include TR::CondUtils
11
+
12
+ attr_reader :name
13
+
14
+ def initialize(name, &block)
15
+ @name = name
16
+ instance_eval(&block) if block
17
+ end
18
+
19
+ def store_root(path)
20
+ @root = path
21
+ FileUtils.mkdir_p(@root) if not File.exist?(@root)
22
+ end
23
+
24
+ def root
25
+ raise ConfigError, "FsAttachable storage root is not set. Please set it via store_root before using the class" if is_empty?(@root)
26
+ @root.freeze
27
+ end
28
+
29
+ end # class ConfigDomain
30
+
31
+ class Config
32
+ include TR::CondUtils
33
+ include Singleton
34
+
35
+ def parse(&block)
36
+ instance_eval(&block)
37
+ end
38
+
39
+ def domain(name, &block)
40
+ cd = ConfigDomain.new(name, &block)
41
+ domains[cd.name.to_sym] = cd
42
+ cd
43
+ end
44
+
45
+ def for_domain(name)
46
+ dom = domains[name.to_sym]
47
+ raise DomainNotSet, "Given domain '#{name}' is not avaialble" if dom.nil?
48
+ dom
49
+ end
50
+
51
+ private
52
+ def domains
53
+ if @_domains.nil?
54
+ @_domains = {}
55
+ end
56
+ @_domains
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FsAttachable
4
+ VERSION = "0.1.1"
5
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'teLogger'
4
+ require 'toolrack'
5
+
6
+ require_relative "fs_attachable/version"
7
+ require_relative "fs_attachable/attachable_config"
8
+
9
+ module FsAttachable
10
+ include TR::CondUtils
11
+
12
+ class Error < StandardError; end
13
+ class SourceFileNotFound < StandardError; end
14
+ class DomainNotSet < StandardError; end
15
+
16
+ def self.config(&block)
17
+ Config.instance.parse(&block)
18
+ end
19
+
20
+ def self.logger(tag = nil, &block)
21
+ if @_logger.nil?
22
+ @_logger = TeLogger::Tlogger.new
23
+ end
24
+
25
+ if block
26
+ if not_empty?(tag)
27
+ @_logger.with_tag(tag, &block)
28
+ else
29
+ @_logger.with_tag(@_logger.tag, &block)
30
+ end
31
+ else
32
+ if is_empty?(tag)
33
+ @_logger.tag = :fs_att
34
+ @_logger
35
+ else
36
+ # no block but tag is given? hmm
37
+ @_logger.tag = tag
38
+ @_logger
39
+ end
40
+ end
41
+
42
+ end # def logger
43
+
44
+
45
+ module ClassMethods
46
+ include TR::CondUtils
47
+
48
+ def domain(name)
49
+ @domain = name
50
+ end
51
+
52
+ def class_domain
53
+ @domain
54
+ end
55
+
56
+ def logger
57
+ FsAttachable.logger(:c_opLog)
58
+ end
59
+
60
+ end
61
+ def self.included(klass)
62
+ klass.extend(ClassMethods)
63
+ end
64
+
65
+ ## Instance methods
66
+ def has_attachments?(name = nil, opts = {})
67
+
68
+ if is_empty?(name)
69
+ tpath = config.root
70
+ if File.exist?(tpath)
71
+ files = Dir.entries(tpath)
72
+ logger.debug "Files at managed storage '#{tpath}' : #{files.length}"
73
+ files.length > 2
74
+ else
75
+ false
76
+ end
77
+ else
78
+ res, path, _ = find_attachment(name, opts)
79
+ if res and File.directory?(path)
80
+ false
81
+ else
82
+ res
83
+ end
84
+ end
85
+ end
86
+ alias_method :has_attachment?, :has_attachments?
87
+
88
+ #
89
+ # Upload given path into managed storage
90
+ #
91
+ def upload_attachment(path, opts = {})
92
+
93
+ raise Error, "Source path must be given" if is_empty?(path)
94
+
95
+ opts = {} if opts.nil?
96
+
97
+ if File.exist?(path)
98
+
99
+ dest_file_name = opts[:dest_file_name]
100
+ dest_file_name = File.basename(path) if is_empty?(dest_file_name)
101
+
102
+ if not_empty?(opts[:root])
103
+ pa = File.join(config.root, opts[:root], dest_file_name)
104
+ FileUtils.mkdir_p(File.dirname(pa)) if not File.exist?(File.dirname(pa))
105
+ else
106
+ pa = File.join(config.root, dest_file_name)
107
+ end
108
+
109
+ FileUtils.cp(path, pa)
110
+
111
+ if not_empty?(opts[:object_class]) and not_empty?(opts[:object_id])
112
+ attMeta = ModelFact.new_instance(:fsAtt_meta, true)
113
+ attMeta.objClass = opts[:object_class]
114
+ attMeta.objId = opts[:object_id]
115
+ attMeta.mstorage_path = pa
116
+ attMeta.save
117
+ end
118
+
119
+ pa
120
+
121
+ else
122
+ raise SourceFileNotFound, "Given file '#{path}' not found"
123
+ end
124
+ end
125
+
126
+ def open_attachment(dest_file_name, opts = { }, &block)
127
+
128
+ raise Error, "Block is required for open_attachment" if not block
129
+ raise Error, "Destination file name must be given" if is_empty?(dest_file_name)
130
+
131
+ opts = { } if opts.nil?
132
+
133
+ if not_empty?(opts[:root])
134
+ pa = File.join(config.root, opts[:root], dest_file_name)
135
+ FileUtils.mkdir_p(File.dirname(pa)) if not File.exist?(File.dirname(pa))
136
+ else
137
+ pa = File.join(config.root, dest_file_name)
138
+ end
139
+
140
+ if block
141
+ File.open(pa,"wb") do |f|
142
+ block.call(f)
143
+ end
144
+
145
+ if not_empty?(opts[:object_class]) and not_empty?(opts[:object_id])
146
+ attMeta = ModelFact.new_instance(:fsAtt_meta, true)
147
+ attMeta.objClass = opts[:object_class]
148
+ attMeta.objId = opts[:object_id]
149
+ attMeta.mstorage_path = pa
150
+ attMeta.save
151
+ end
152
+ end
153
+
154
+ pa
155
+ end
156
+
157
+ def find_attachment(name, opts = { raise_if_not_found: false })
158
+
159
+ opts = {} if opts.nil?
160
+ raiseIfNotFound = opts[:raise_if_not_found]
161
+ raiseIfNotFound = false if is_empty?(raiseIfNotFound) or not_bool?(raiseIfNotFound)
162
+
163
+ objClass = opts[:object_class] || nil
164
+ objId = opts[:object_id] || nil
165
+
166
+ if not_empty?(objClass) and not_empty?(objId)
167
+ attMeta = ModelFact.class_instance(:fsAtt_meta, true)
168
+ rec = attMeta.record_with(objClass: objClass, objId: objId, name: name)
169
+ if not_empty?(rec)
170
+ @arec = rec.first
171
+ pa = @arec.mstorage_path
172
+ else
173
+ raise SourceFileNotFound, "File '#{name}' is not found in storage of object '#{objClass}' and ID '#{objId}'"
174
+ end
175
+ else
176
+ pa = File.join(config.root, name)
177
+ end
178
+
179
+ logger.debug "Looking for attachment at : #{pa}"
180
+ if File.exist?(pa)
181
+ [true, pa, @arec]
182
+ else
183
+ if raiseIfNotFound
184
+ raise SourceFileNotFound, "File '#{name}' is not found in storage"
185
+ else
186
+ [false, nil]
187
+ end
188
+ end
189
+
190
+ end
191
+
192
+ def remove_attachment(name, opts = { })
193
+
194
+ res, path, rec = find_attachment(name, opts)
195
+ if res
196
+ FileUtils.remove_entry_secure(path)
197
+ rec.destroy if not rec.nil?
198
+
199
+ dir = File.dirname(path)
200
+ if dir != "." and dir != config.root
201
+ FileUtils.remove_dir(dir) if Dir.entries(dir).length == 2
202
+ end
203
+ end
204
+ [res, path]
205
+ end
206
+
207
+ def remove_attachments
208
+ root = config.root
209
+ FileUtils.remove_entry_secure(root, true)
210
+ end
211
+
212
+ private
213
+ def logger
214
+ FsAttachable.logger(:opLog)
215
+ end
216
+
217
+ def verify_if_domain_set
218
+ if is_empty?(self.class.class_domain)
219
+ raise DomainNotSet, "Class '#{self.class}' has no domain set"
220
+ else
221
+ logger.debug "class domain : #{self.class.class_domain}"
222
+ end
223
+ end
224
+
225
+ def config
226
+ verify_if_domain_set
227
+ dom = Config.instance.for_domain(self.class.class_domain)
228
+ logger.debug "domain : #{dom}"
229
+ dom
230
+ end
231
+
232
+ end
@@ -0,0 +1,4 @@
1
+ module FsAttachable
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fs_attachable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-10-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: toolrack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: teLogger
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: release-gem
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: ''
56
+ email:
57
+ - chris@antrapol.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".rspec"
63
+ - README.md
64
+ - Rakefile
65
+ - lib/fs_attachable.rb
66
+ - lib/fs_attachable/attachable_config.rb
67
+ - lib/fs_attachable/version.rb
68
+ - sig/fs_attachable.rbs
69
+ homepage: ''
70
+ licenses: []
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.6.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubygems_version: 3.4.6
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: ''
91
+ test_files: []