Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/benthorner/activefolder

A file system ORM based on ActiveRecord
https://github.com/benthorner/activefolder

Last synced: 3 months ago
JSON representation

A file system ORM based on ActiveRecord

Awesome Lists containing this project

README

        

# ActiveFolder

## A file system ORM based on ActiveRecord

ActiveFolder gives you programmatic access to the file system at a high level of abstraction, mapping objects to files, and relations to folders.

### Introduction

To get started, require the gem and you're ready to go!

require 'activefolder'

Now create a model to interact with your database.

class City < ActiveFolder::Base; end

City.create(name: 'London')
=> #

City.all
=> [#]

Dir.glob('**/*')
=> ["cities", "cities/London", "cities/London/attributes.yaml"]

You can also define relationships between models.

class Country < ActiveFolder::Base
has_many :cities
end

uk = Country.create(name: 'UK')
=> #

uk.cities.create(name: "London")
=> #

uk.cities.all
=> [#]

Read on for more details and examples.

### Configuration

ActiveFolder supports the following configuration.

ActiveFolder.setup do |config|
config.client.root_path = '.' # (default) relative/absolute path
end

### Usage

#### Enumeration

Assume the following elements.

Country.create(name: 'UK', languages: ['English'], area: 0.24)
Country.create(name: 'Canada', languages: ['English', 'French'], area: 9.99)
Country.create(name: 'Argentina', languages: ['Spanish'], area: 2.78)

You can then do some simple queries.

Country.all
=> [#, #, #]

Country.first # => #
Country.last # => #

Country.find('UK') # => #
Country.count # => 3

Country.find!('Australia')
ActiveFolder::Model::NotFoundError: bar

You can also do complex queries.

Country.where(name: /na/)
=> [#, #]

Country.where(area: 0..3)
=> [#, #]

Country.where(name: /.*/, languages: ['English'])
=> [#, #]

The next section has an example with deep nesting.

#### Relation

Here's a more complicated example.

class Country < ActiveModel::Base
has_many :cities
has_many :streets
has_one :currency
end

class City < ActiveModel::Base
belongs_to :country
has_many :streets
end

class Street < ActiveModel::Base
belongs_to :city
belongs_to :country
end

class Currency < ActiveModel::Base; end

This creates a 3-level hierarchy.

uk = Country.create(name: 'UK')
london = uk.cities.create(name: 'London')

street = london.streets.create(name: 'Downing Street')
lane = uk.streets.create(name: 'Country Lane')

gbp = Currency.create(name: 'GBP')
uk.currency = gbp

Queries are then scoped by level.

uk.streets.all
=> [#, #]

london.streets.all
=> [#]

london.country => #
street.country => #

street.city => #
lane.city => nil

uk.currency
=> #

Complex queries can go across relations.

Country.where(streets: [{ name: 'Country Lane' }])
=> [#]

Country.where(cities: [streets: [{ name: /Downing/ }]}])
=> [#]

#### Collection

Normal create/destroy is supported...

Country.create(name: 'UK', area: 0.24)
=> #

Country.find_or_create(name: 'UK', languages: ['English'])
=> #

Country.create!(name: 'UK')
ActiveFolder::Model::DuplicateError: UK

Country.destroy_all
=> [#]

...as well as build/initialize.

Country.build(name: 'UK', area: 0.24)
=> #

Country.find_or_initialize(name: 'UK', languages: ['English'])
=> #

#### Validation

Validation works like `where` for a single attribute.

class Country < ActiveFolder::Base
validate :languages, ['English', 'Spanish']
end

Each attribute can have multiple validations.

class Country < ActiveFolder::Base
validate :languages, Array, 'languages must be an array'
end

#### Persistence

Each object can load/save its attributes.

Country.create(name: 'UK', area: 0.24)
=> #

uk = Country.new(name: 'UK', base_dir: '/countries')
=> #

uk.load
=> #

uk.languages = ['English']; uk.save
=> #

You can also destroy and update objects.

uk.update(area: 0.25) # The beginning of the empire
=> #

uk.destroy
=> ["./countries/UK"]

Objects attributes are stored as YAML.

#### Discovery

Discover an object's heritage...

uk = Country.create(name: 'UK')
london = uk.cities.create(name: 'London')

london.path => '/countries/uk/cities/London'

Country.find_by_path(london.path)
=> #

Useful for command line programs.

### Testing

Keep your test directory clean...

require 'activefolder/rspec' # Cleanup around examples

Cleanup deletes the ActiveFolder root path.