Import and export directories with an ORM-like interface.
Add this line to your application's Gemfile:
gem 'dir_model'
And then execute:
$ bundle
Or install it yourself as:
$ gem install dir_model
class BasicDirModel
include DirModel::Model
file :image, regex: -> { /Zones\/Sector_(?<sector_id>.*)\/Zone_(?<zone_id>.*)\.(?<extension>png|jpg)/i }
end
named matches are available under matches[:sector_id]
or directly when you calling sector_id
An implementation possible of Import
class BasicImportDirModel < BasicDirModel
include DirModel::Import
protected
def model
Project.find(context[:project_id]).sectors.find(sector_id).zones.find(zone_id)
end
end
You can have access at the file through
BasicImportDirModel.new(source_path, project_id: 42).image
A dir_model can have a relation like has_one
basically is
class ChildImportDirModel
include DirModel::Model
include DirModel::Import
file :metadata, regex: ->(foreign_value) { "Zones\/(?<sector_name>#{foreign_value})\/Zone_(?<zone_id>.*)\.(?<extension>json)" }
end
class ParentImportDirModel < BasicImportDirModel
has_one :dependency, ChildImportDirModel, foreign_key: :sector_name
def sector_name
"sector_#{sector_id}"
end
end
parent_instance.dependency # => ChildImportDirModel
child.parent # => parent_instance
You can define an has_many
relation with another DirModel
, is this case syntax is a bit different you have to pass a foreign_key
, basically the name of the method should return a value will be replace in the regex in children relationships, like examples below
NOTE regex on child pass explicitly the value
class ZoneDirModel
include DirModel::Model
include DirModel::Import
file :image, regex: ->(foreign_value) { "Zones\/(?<sector_name>#{foreign_value})\/Zone_(?<zone_id>.*)\.(?<extension>png|jpg)" }
end
class SectorDirModel
include DirModel::Model
file :image, regex: -> { /Sectors\/Sector_(?<sector_id>.*)\.(?<extension>png|jpg)/i }
end
class SectorImportDirModel < SectorDirModel
include DirModel::Import
has_many :dependencies, ZoneDirModel, foreign_key: :sector_name
def sector_name
'sector_1'
end
end
DirModel::Import::Dir
can be subclassed to access
ActiveModel::Callbacks
.
- next -
before
,around
, orafter
each change incurrent_dir_model
and implement the callbacks:
class ImportDir < DirModel::Import::Dir
before_next :track_progress
def track_progress
...
end
end
class BasicDirModel
include DirModel::Model
file :image, path: -> { "#{dir}/#{sub_dir}" }, name: -> { image_name }
end
path
and name
can take Proc or String if doesn't have any interpolation.
If you don't know the extension of your image it will be automatically discover, but this works only for image so if you send, for instance, a json file you have to explicitly provide extension on the :name
options
class BasicExportDirModel < BasicDirModel
include DirModel::Export
def dir
'Sectors'
end
def sub_dir
source_model.sector_name
end
def image_name
source_model.zone_name
end
def image
source_model.zone
end
def image_extension
'.png'
end
end
fixture_models = [
OpenStruct.new({
id: 42,
sector_name: 'sector_name',
zone_name: 'zone_name',
zone: File.new('spec/fixtures/image.png'),
})
]
exporter = DirModel::Export::AggregateDir.new
exporter.generate do |dir|
models.each do |model|
dir.append_model(BasicExportDirModel, model)
end
end
exporter.dir_path # => path of generated dir .../Sectors
an skip? method based on the name of file :image is create, this method is named image_skip?
default implementation
def skip?
image.present?
end
NOTE Safe to override on your Exporter
In fact this is equivalent to
def skip?
source_model.zone.present?
end
by default Exporter provide a link between source_model
and your file
like
def image
source_model.image
end
NOTE Safe to override on your Exporter
In fact this play well with carrierwave and provide for you automatically
def image
source_model.image.file
end
as well Exporter provide extension method only for carrierwave uploader
def image_extension
source_model.image.file.extension
end
Otherwise return nil, safe to override on your Exporter