activefile 0.0.0beta

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTQ1YjFmMGQ2NjI5ZWU4Y2ZjYTNhYjY2NjQwYTE1ZDcxZmI4ODM4ZQ==
5
+ data.tar.gz: !binary |-
6
+ NGZhMzQwMDY4NzVmNjMxZTY2NjFmYzhjMjliNWU5OTQwMjQ1ZjhjOQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YTFhZjEyNDZiYWE4ZTAwNTE0MGQzZWQ5NjQ0NzNmMTAwMWQ0MjYwMWM2MTRm
10
+ ZmU3ZThiODUzNzY0Yzc1N2U1YmM1YjQ4YjA2YjI2ODg5ZTE0OTkyMWQ2NWYz
11
+ MjMwZmI3ZDBlNTAyOTFhNjE4NjczZThkM2VmZDc3MjA4ZjkyNGQ=
12
+ data.tar.gz: !binary |-
13
+ OTU4ZmZjN2RmMGJmZTUxYjM1OTk4YmVjMDczNDQ5NzFkYjQ3MTEwNGY5OGQ2
14
+ MmYzNWMwNzFlNjcwZTljZDE0OTliMmMzZjM2OTI1MTJlNDczZGJmN2Q5YWIy
15
+ OTNjZWIxZDU2ODk5ZWRlNzY0NjI0ZGVjM2MyNjM3NTdmMjJhZGY=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,35 @@
1
+ == Gem under construction. Base functionality already done, but I still need reorganize it. I work with Unit tests now.
2
+
3
+ Please, be patient! All work will be done untill May.
4
+
5
+ == Welcome to ActiveFile
6
+
7
+ ActiveFile is a lightweight file system ORM.
8
+
9
+ Build a persistent domain model by mapping file system objects to Ruby classes. It inherits ActiveRecord-similar interface.
10
+
11
+
12
+
13
+ class Shop < ActiveFile::Base
14
+ parent_to :product
15
+ end
16
+
17
+ class Product < ActiveFile::Base
18
+ child_of :shop
19
+ end
20
+
21
+ shop = Shop.new(:name => "Apple Store")
22
+ shop.save!
23
+
24
+ Shop.all.size #> 1
25
+
26
+ iPad = Product.new(:name => "iPad", :parent => shop, :data => "The iPad is a line of tablet computers designed and marketed by Apple Inc., which runs Apple's iOS operating system.")
27
+ iPad.save!
28
+
29
+ product = Product.where(:name => "iPad")[0]
30
+ product.data #> "The iPad "...
31
+ product.shop #> <Shop instance>
32
+ product.shop.name #> "Apple Store"
33
+
34
+
35
+ # In result, two persistent files were created, accessible via ORM mechanism.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+
2
+ desc "Default Task"
3
+ task default: [ :test ]
4
+
5
+ # Run the unit tests
6
+ #Rake::TestTask.new { |t|
7
+ ## t.libs << "test"
8
+ # t.pattern = 'test/**/*_test.rb'
9
+ # t.warning = true
10
+ # t.verbose = true
11
+ #}
12
+
13
+ task :test do
14
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
15
+ Dir.glob("test/**/*_test.rb").all? do |file|
16
+ sh(ruby, '-Ilib:test', file)
17
+ end or raise "Failures"
18
+ end
@@ -0,0 +1,273 @@
1
+ module ActiveFile
2
+ # Data Source Storage Adapter
3
+ module Adapter
4
+ require 'fileutils'
5
+ RAISE_TRUE = true
6
+ RAISE_FALSE = false
7
+
8
+ def initialize args
9
+ super args
10
+ end
11
+
12
+ def base_folder arg
13
+ puts "BaseFolder is #{arg}"
14
+ end
15
+
16
+
17
+ # touch file to read!
18
+ def load!
19
+ self.data
20
+ self
21
+ end
22
+
23
+ def data= data_arg
24
+ @self_data = data_arg
25
+ end
26
+
27
+ def data
28
+ if @self_data == nil
29
+ @self_data = File.read(self.get_source_path)
30
+ end
31
+ @self_data || ""
32
+ end
33
+
34
+ # Main rule to link attaches (css) with their targets (layouts, contents). Special filename format used for this purpose;
35
+ def attach_my_name!
36
+ # Is we an attached instance?
37
+ unless self.target.nil?
38
+ #@ext = CSS_EXT if self.type == SourceType::CSS
39
+ self.name = target.type.to_s + TARGET_DIVIDER + target.name #+ @ext.to_s
40
+ end
41
+ end
42
+
43
+ # Get source folder. Create, if not exists.
44
+ def get_source_folder
45
+ Adapter.get_source_folder(type)
46
+ end
47
+ def get_name
48
+ attach_my_name!
49
+ return name
50
+ end
51
+ # Get source filename
52
+ def get_filename
53
+ get_name + get_extension
54
+ end
55
+ # Alias for get_source_path
56
+ def get_filepath
57
+ get_source_path
58
+ end
59
+ # Get source path. For targeted objects, target name + '--' + target type appends
60
+ def get_source_path
61
+ raise ArgumentError, 'Name can not be blank!' if name.blank? && target.nil?
62
+ raise ArgumentError, 'Target name can not be blank!' if target && target.name.blank?
63
+ get_source_folder + get_filename
64
+ end
65
+ def get_extension
66
+ return ".scss" if type == SourceType::CSS
67
+ return extension.blank? ? "" : "."+extension
68
+
69
+ type_ext = SOURCE_TYPE_EXTENSIONS[type.to_i] || ""
70
+ return "" if type_ext == "*"
71
+ if type_ext == "*"
72
+ unless new_record?
73
+ # Custom extension, from filename
74
+ Dir.glob(dir+"*").each do |f|
75
+ name_with_extension = f.split('/').last
76
+ name, ext = name_with_extension.split('.')
77
+ if name == get_name
78
+ type_ext = ext
79
+ break
80
+ end
81
+ end
82
+ else
83
+ _name, _ext = name.split(".")
84
+ unless _name.empty? && _ext.empty?
85
+ type_ext = _ext
86
+ end
87
+ end
88
+ end
89
+ type_ext = "." + type_ext unless type_ext.empty?
90
+ type_ext
91
+ end
92
+ # Get unique id of the source
93
+ def get_id
94
+ ID_PREFIX + type.to_s + ID_DIVIDER + get_name
95
+ end
96
+ # Rename the source file, return boolean operation result
97
+ def rename(new_file_name)
98
+ raise "Source is new record, call the save! method before rename." if new_record?
99
+ # rename attached file, if present ()
100
+ attach = get_attach
101
+ # later..
102
+ old_file_path = get_source_path
103
+ new_file_path = get_source_folder + new_file_name + get_extension
104
+ b_result = !!File.rename(old_file_path, new_file_path)
105
+ raise "Unable to rename source" unless b_result
106
+ self.name = new_file_name
107
+ if attach
108
+ # to rename attach, create new copy of attached object with new target name, and delete old
109
+ attach_source = attach.clone
110
+ attach_source.target = self
111
+ b_result = attach_source.save! && attach.delete!
112
+ raise 'Attached file rename failed' unless b_result
113
+ end
114
+ b_result
115
+ end
116
+ def new_record?
117
+ p get_source_path
118
+ !File.exists?(get_source_path)
119
+ end
120
+ private
121
+ def save_method(raise_exception_on_error)
122
+ File.open(get_source_path, "w") do
123
+ |file| file.write(data.force_encoding('utf-8'))
124
+ end
125
+ rescue => e
126
+ return raise_exception_on_error == RAISE_TRUE ? raise(e) : false
127
+ end
128
+ def delete_method(raise_exception_on_error)
129
+ delete_file_name = get_source_path
130
+ File.delete(delete_file_name)
131
+ return true
132
+ rescue => e
133
+ return raise_exception_on_error == RAISE_TRUE ? raise(e) : false
134
+ end
135
+ public
136
+ # Save the source, return boolean operation result
137
+ def save
138
+ save_method(RAISE_FALSE)
139
+ end
140
+ def save!
141
+ save_method(RAISE_TRUE)
142
+ end
143
+ # Delete the source: if successful returns true, else return false
144
+ def delete
145
+ delete_method(RAISE_FALSE)
146
+ end
147
+ # Delete the source: if successful returns true, else raise an error
148
+ def delete!
149
+ raise StandardError, "Unable to delete file if object hasn't been saved yet" if new_record?
150
+ delete_method(RAISE_TRUE)
151
+ end
152
+ def get_target_type
153
+ name.split(TARGET_DIVIDER)[0]
154
+ end
155
+ def get_target_name
156
+ name.split(TARGET_DIVIDER)[1]
157
+ end
158
+ # Get target object
159
+ def get_target
160
+ return nil unless name.include?(TARGET_DIVIDER)
161
+ #target_type, target_name = name[0..-2].split(TARGET_DIVIDER)
162
+ target_type = get_target_type
163
+ target_name = get_target_name
164
+
165
+ target_type_extension = SOURCE_TYPE_EXTENSIONS[target_type.to_i]
166
+ unless target_type_extension.empty?
167
+ target_type_extension = "." + target_type_extension
168
+ end
169
+
170
+ target = Adapter.get_source_folder(target_type) + target_name + target_type_extension
171
+ return nil unless File.exists?(target)
172
+ return Source.new({ :type => target_type.to_i, :name => target_name, :data => nil })
173
+ end
174
+ # Get attached object
175
+ def get_attach attach_type=SourceType::CSS
176
+ Adapter.where(:type => attach_type, :name => get_attached_name).first
177
+ end
178
+ def get_attached_name
179
+ type.to_s + TARGET_DIVIDER + name
180
+ end
181
+ #def get_attached_filename
182
+ # attached_file_extension = SOURCE_TYPE_EXTENSIONS[attach_type.to_i]
183
+ # attached_file_extension = "." + attached_file_extension unless attached_file_extension.empty?
184
+ # type.to_s + TARGET_DIVIDER + name + attached_file_extension
185
+ #end
186
+ def get_attach_or_create attach_type=SourceType::CSS
187
+ attach = get_attach(attach_type)
188
+ if attach.nil?
189
+ attach = Source.new(:type => attach_type, :extension => SOURCE_TYPE_EXTENSIONS[attach_type])
190
+ attach.target = self
191
+ attach.save!
192
+ end
193
+ attach
194
+ end
195
+ #
196
+ # STATIC METHODS MODULE
197
+ module ClassMethods
198
+ # Creates a new source instance and saves it to disk. Returns the newly created source. If a failure has occurred or source already exists -
199
+ # an exception will be raised.
200
+ def create(attributes={})
201
+ raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
202
+ source_instance = Source.new(attributes)
203
+ raise 'Source file with such name already exists!' if File.exists?(source_instance.get_source_path)
204
+ source_instance.save!
205
+ return source_instance
206
+ end
207
+ # Get source folder for any source type. Create, if not exists.
208
+ def get_source_folder(type)
209
+ source_folder = Rails.env == 'test' ? TEST_SOURCE_FOLDERS[type.to_i || SourceType::UNDEFINED] : SOURCE_FOLDERS[type.to_i || SourceType::UNDEFINED]
210
+ FileUtils.mkpath(source_folder) unless File.exists?(source_folder)
211
+ return source_folder
212
+ end
213
+ # Get names array of all sources with specified type
214
+ def all_by_type(source_type)
215
+ files = Array.new
216
+ dir = Adapter.get_source_folder(source_type)
217
+ source_extension = SOURCE_TYPE_EXTENSIONS[source_type.to_i]
218
+
219
+ Dir.glob(dir+"*").each do |f|
220
+ name_with_extension = f.split('/').last
221
+ extension = name_with_extension.split('.').size > 1 ? name_with_extension.split('.').last : ""
222
+ name_without_extension = nil
223
+
224
+ name_without_extension = name_with_extension
225
+
226
+ if source_extension.blank?
227
+ name_without_extension = name_with_extension
228
+ else
229
+ name_without_extension = source_extension == "*" ? name_with_extension.split('.').first : name_with_extension[0..-source_extension.length-2]
230
+ end
231
+
232
+ s = Source.new({ :type => source_type, :name => name_without_extension, :extension => extension, :data => nil })
233
+ target_object = s.get_target
234
+ s.target = target_object unless target_object.nil?
235
+ files.push(s)
236
+ end
237
+ return files
238
+ end
239
+ def all
240
+ (Rails.env == 'test' ? TEST_SOURCE_FOLDERS : SOURCE_FOLDERS).map {|key_type, val| Adapter.all_by_type(key_type) }.reject { |ar| ar.empty? }.flatten
241
+ end
242
+ # Find the source
243
+ def where(attributes)
244
+ raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
245
+ Adapter.all.select do |source|
246
+ match = true
247
+ attributes.each{|key, val|
248
+ match = false if source.send(key) != val
249
+ }
250
+ match
251
+ end
252
+ end
253
+ def find_by_id(id)
254
+ id = id[ID_PREFIX.size .. -1]
255
+ type, name = id.include?(TARGET_DIVIDER) ? (id).split(ID_DIVIDER) : id.split(ID_DIVIDER)
256
+ Adapter.find_by_name_and_type(name, type.to_i).first
257
+ end
258
+ # Complex finders:
259
+ def method_missing(m, *args, &block)
260
+ if m.to_s.index("find_by_") == 0
261
+ attributes = m["find_by_".size..-1].split("_and_")
262
+ raise "Attributes count expected: #{attributes.size}, got: #{args.size}" unless attributes.size == args.size
263
+ match_hash = {}
264
+ attributes.each_with_index {|attr, index| match_hash[attr.to_sym] = args[index]}
265
+ return Adapter.where(match_hash)
266
+ else
267
+ puts "There's no method called #{m} here -- please try again with args #{args}"
268
+ end
269
+ end
270
+ end
271
+ extend ClassMethods
272
+ end
273
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveFile
2
+ require 'ostruct'
3
+ class Base < OpenStruct
4
+
5
+
6
+ include Adapter
7
+ extend Adapter::ClassMethods
8
+ def ahola
9
+ puts 'ahols here!'
10
+ end
11
+ #'a'.camelize.safe_constantize
12
+ #def child_of(parent_name)
13
+ # puts "ok, I am a child of #{parent_name}"
14
+ #end
15
+ #
16
+ #def parent_to(child_name)
17
+ # puts "OH, I am a parent to #{child_name}"
18
+ #end
19
+
20
+ end
21
+ end
data/lib/activefile.rb ADDED
@@ -0,0 +1,29 @@
1
+ #--
2
+ # Copyright (c) 2013 ariekdev
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require "active_support/dependencies/autoload"
25
+ module ActiveFile
26
+ extend ActiveSupport::Autoload
27
+ autoload :Base
28
+ autoload :Adapter
29
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activefile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0beta
5
+ platform: ruby
6
+ authors:
7
+ - Vitaly Pestov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-16 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Build a hierarchical model of filesystem objects.
14
+ email: vitalyp@softwareplanet.uk.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/activefile.rb
20
+ - lib/active_file/adapter.rb
21
+ - lib/active_file/base.rb
22
+ - MIT-LICENSE
23
+ - Rakefile
24
+ - README.rdoc
25
+ homepage: http://www.interlink-ua.com
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.9.3
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>'
41
+ - !ruby/object:Gem::Version
42
+ version: 1.3.1
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.0.2
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Object-relational mapper framework. Please, be patient. Under construction.
49
+ test_files: []