Class: EPO::DB

Inherits:
Object
  • Object
show all
Includes:
Derailleur::Application
Defined in:
lib/epo/core/db.rb

Defined Under Namespace

Classes: PrepareDirAction, StoreResourceAction

Constant Summary collapse

RESOURCE_REGEXP =
%r{resource-epo-\w+}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(models, params = {}) ⇒ DB

Creates a new DB models: the list of Welo::Resource models to use (i.e., classes)



20
21
22
23
24
25
# File 'lib/epo/core/db.rb', line 20

def initialize(models, params={})
  @models = models
  @extensions = params[:extensions] || ['.json']
  @identifying_sym = params[:identifying_sym] || :flat_db
  build!
end

Instance Attribute Details

#extensionsObject (readonly)

A list of understood extensions (e.g., ‘.json’, ‘.yaml’), default is ‘.json’



13
14
15
# File 'lib/epo/core/db.rb', line 13

def extensions
  @extensions
end

#identifying_symObject (readonly)

The name of the identifiers to use to map Welo::Resources to directories



16
17
18
# File 'lib/epo/core/db.rb', line 16

def identifying_sym
  @identifying_sym
end

#modelsObject (readonly)

The list of understood models, models must behave like Welo::Resources



10
11
12
# File 'lib/epo/core/db.rb', line 10

def models
  @models
end

Instance Method Details

#basename_for_persp_and_ext(persp, ext) ⇒ Object

Returns the basename of a resource blob for a perspective named persp and in a format with extension ext (including the leading dot).

see also persp_and_ext_for_basename



111
112
113
# File 'lib/epo/core/db.rb', line 111

def basename_for_persp_and_ext(persp, ext)
  "resource-epo-#{persp}#{ext}"
end

#batch_save(root, resources, persps, exts) ⇒ Object

Saves all the resources, under all the perspectives persps, and all format given by extensions exts at the filesystem path root. resources, perps, exts, must respond to :each, like for Enumerable



164
165
166
167
168
# File 'lib/epo/core/db.rb', line 164

def batch_save(root, resources, persps, exts)
  batch_save_actions(root, resources, persps, exts) do |action|
    action.perform
  end
end

#batch_save_actions(root, resources, persps, exts) ⇒ Object

Yields all the action needed to store all the resources at perspectives persps and with formats exts. All actions respond to :perform (it is when they’re executed). If no block given, returns an Enumerator with these actions.



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/epo/core/db.rb', line 174

def batch_save_actions(root, resources, persps, exts)
  if block_given?
    resources.each do |resource|
      db_path = File.join(root, resource.path(identifying_sym))
      yield PrepareDirAction.new(db_path)
      exts.each do |ext|
        persps.each do |persp|
          basename = basename_for_persp_and_ext(persp, ext)
          resource_path = File.join(db_path, basename) 
          yield StoreResourceAction.new(resource_path, resource, persp, ext)
        end
      end
    end
  else
    Enumerator.new(self, :batch_save_actions, root, resources, persps, exts)
  end
end

#build_route_for_model(model) ⇒ Object

Registers a model on a derailleur node at its path_model Does not modify self.models



41
42
43
44
45
# File 'lib/epo/core/db.rb', line 41

def build_route_for_model(model)
  path = File.join(model.path_model(identifying_sym), ':filename')
  node = build_route(path)
  node.content = model
end

#delete(root, resource) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/epo/core/db.rb', line 133

def delete(root, resource)
  remaining_path = File.join(root, resource.path(identifying_sym))
  # removes the resource-epo-* files
  Dir.entries(remaining_path).each do |e|
    if e.start_with?('resource-epo-')
      FileUtils.rm(File.join(remaining_path, e)) 
    end
  end

  # removes the empty directories upward
  resource.identifiers(identifying_sym).size.times do |t|
    begin
      Dir.rmdir(remaining_path)
      remaining_path = File.split(remaining_path).first
    rescue Errno::ENOTEMPTY
      break
    end
  end
end

#delete_completely(root, resource) ⇒ Object

Deletes a resource by removing its identifying directory. Beware because this method doesn’t care about other files which may coexist in the same filesystem branch.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/epo/core/db.rb', line 118

def delete_completely(root, resource)
  path = File.join(root, resource.path(identifying_sym))
  FileUtils.rm_rf(path)

  # removes the empty directories upward
  (resource.identifiers(identifying_sym).size - 1).times do |t|
    path = File.split(path).first
    begin
      FileUtils.rmdir(path)
    rescue Errno::ENOTEMPTY
      break
    end
  end
end

#each_resource_observation(root) ⇒ Object

Iterates on every resource found and understood in the filesystem directory root. If no block is given, returns an iterator.



233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/epo/core/db.rb', line 233

def each_resource_observation(root) 
  if block_given?
    xp = observer
    models.each do |model|
      xp.on(model) do |obs|
        yield obs
      end
    end
    xp.read_tree(root)
  else
    Enumerator.new(self, :each_resource_observation, root)
  end
end

#main_name(path) ⇒ Object

Returns the main name of a path, i.e., the basename without the extension

  • main_name(‘/a/b/c/foo.bar’) #=> ‘foo’



81
82
83
# File 'lib/epo/core/db.rb', line 81

def main_name(path)
  File.basename(path).sub(/\.[^\.]+$/,'')
end

#observerObject

Returns a new EPO::Observer for itself



226
227
228
# File 'lib/epo/core/db.rb', line 226

def observer
  Observer.for_db(self)
end

#persp_and_ext_for_basename(path) ⇒ Object

Returns the perspective name and extension name (a 2 items array) for the given path. By default the blobs for resources content are stored in files named ‘resource-<persp><ext>’ with ext starting with a dot



104
105
106
# File 'lib/epo/core/db.rb', line 104

def persp_and_ext_for_basename(path)
  [main_name(path).sub('resource-epo-',''), File.extname(path)]
end

#read_file(path) ⇒ Object

Loads the file at path and turn it to a ruby object based on the file extension. If the file extension is not supported, will raise an error. uses JSON.parse(File.read(path)) and YAML.load_file(path) for ‘.json’ and ‘.yaml’ otherwise, will forward the handling such that ‘.foobaar’ maps to :read_foobar(path)

Raises:

  • (ArgumentError)


60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/epo/core/db.rb', line 60

def read_file(path)
  raise ArgumentError, "don't know extension #{ext}, use from [#{extensions.join(', ')}]" unless understands_ext?(path)
  ext = File.extname(path)
  case ext
  when '.json'
    JSON.parse(File.read(path))
  when '.yaml'
    YAML.load_file(path)
  else
    self.send "read_#{ext.tr('.','')}", path
  end
end

#register_model(model) ⇒ Object

Updates self.models and build a route for the model raise an error if the model is already known

Raises:

  • (ArgumentError)


49
50
51
52
53
# File 'lib/epo/core/db.rb', line 49

def register_model(model)
  raise ArgumentError, "already know this model" if models.include?(model)
  models << model
  build_route_for_model(model)
end

#resource_regexpObject



96
97
98
# File 'lib/epo/core/db.rb', line 96

def resource_regexp
  RESOURCE_REGEXP
end

#save(root, resource, perspective = :default, exts = nil) ⇒ Object

Saves one or more resource at the filesystem path given at root This method is mainly an handy helper around batch_save, look at the source and at batch_save’s doc



156
157
158
159
# File 'lib/epo/core/db.rb', line 156

def save(root, resource, perspective=:default, exts=nil)
  exts ||= extensions
  batch_save(root, [resource].flatten, [perspective].flatten, [exts].flatten)
end

#understands_ext?(path) ⇒ Boolean

Wether or not this DB understands the extension of the file at path.

Returns:

  • (Boolean)


74
75
76
# File 'lib/epo/core/db.rb', line 74

def understands_ext?(path)
  extensions.find{|ext| ext == File.extname(path)}
end

#understands_filename?(path) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
88
# File 'lib/epo/core/db.rb', line 85

def understands_filename?(path)
  understands_ext?(path) and
  understands_main_name?(path)
end

#understands_main_name?(path) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/epo/core/db.rb', line 90

def understands_main_name?(path)
  main_name(path) =~ resource_regexp
end