yogo-project 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +27 -0
- data/Gemfile +34 -0
- data/Gemfile.lock +198 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/features/step_definitions/yogo_project_steps.rb +0 -0
- data/features/support/env.rb +1 -0
- data/features/yogo_project.feature +9 -0
- data/lib/datamapper/adapters/postgres.rb +9 -0
- data/lib/datamapper/adapters/sqlite.rb +9 -0
- data/lib/yogo-project.rb +2 -0
- data/lib/yogo/collection.rb +12 -0
- data/lib/yogo/collection/asset.rb +12 -0
- data/lib/yogo/collection/asset/model.rb +11 -0
- data/lib/yogo/collection/asset/model_configuration.rb +21 -0
- data/lib/yogo/collection/asset/model_properties.rb +47 -0
- data/lib/yogo/collection/base.rb +69 -0
- data/lib/yogo/collection/base/collection_repository.rb +21 -0
- data/lib/yogo/collection/base/model.rb +20 -0
- data/lib/yogo/collection/base/model_collection_context.rb +25 -0
- data/lib/yogo/collection/base/model_configuration.rb +34 -0
- data/lib/yogo/collection/data.rb +61 -0
- data/lib/yogo/collection/data/model.rb +72 -0
- data/lib/yogo/collection/data/model_configuration.rb +42 -0
- data/lib/yogo/collection/data/model_properties.rb +15 -0
- data/lib/yogo/collection/field_view.rb +26 -0
- data/lib/yogo/collection/form.rb +22 -0
- data/lib/yogo/collection/property.rb +127 -0
- data/lib/yogo/collection/static.rb +13 -0
- data/lib/yogo/collection/static/model_configuration.rb +31 -0
- data/lib/yogo/configuration.rb +9 -0
- data/lib/yogo/datamapper/model/common/properties.rb +16 -0
- data/lib/yogo/datamapper/model/configuration.rb +31 -0
- data/lib/yogo/datamapper/model/operations/add.rb +34 -0
- data/lib/yogo/datamapper/model/operations/clear.rb +29 -0
- data/lib/yogo/datamapper/model/stored/configuration.rb +25 -0
- data/lib/yogo/datamapper/repository_manager.rb +30 -0
- data/lib/yogo/datamapper/repository_manager/model.rb +40 -0
- data/lib/yogo/datamapper/repository_manager/resource.rb +124 -0
- data/lib/yogo/example/dynamic/project_full.rb +48 -0
- data/lib/yogo/example/dynamic/project_remix.rb +16 -0
- data/lib/yogo/example/voeis/managed/data_stream.rb +39 -0
- data/lib/yogo/example/voeis/managed/site.rb +51 -0
- data/lib/yogo/example/voeis/project.rb +57 -0
- data/lib/yogo/operation.rb +49 -0
- data/lib/yogo/project.rb +32 -0
- data/lib/yogo/property_ext.rb +7 -0
- data/spec/resource/.gitdir +0 -0
- data/spec/resource/text_file_asset.txt +1 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/yogo/all_collection_data_models_spec.rb +34 -0
- data/spec/yogo/all_collection_managers_spec.rb +18 -0
- data/spec/yogo/all_collections_spec.rb +54 -0
- data/spec/yogo/all_data_collections_spec.rb +51 -0
- data/spec/yogo/asset_collection_spec.rb +28 -0
- data/spec/yogo/data_collection_spec.rb +16 -0
- data/yogo-project.gemspec +128 -0
- metadata +222 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'yogo/configuration'
|
2
|
+
require 'yogo/datamapper/model/configuration'
|
3
|
+
require 'yogo/datamapper/model/common/properties'
|
4
|
+
require 'dm-types/yaml'
|
5
|
+
|
6
|
+
DataMapper.setup(:default, :adapter => 'sqlite3', :database => 'dynamic_project.db')
|
7
|
+
|
8
|
+
class ProjectFull
|
9
|
+
include DataMapper::Resource
|
10
|
+
|
11
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
12
|
+
|
13
|
+
property :name, String, :required => true
|
14
|
+
|
15
|
+
has n, :managed_models
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class ManagedModel
|
20
|
+
include DataMapper::Resource
|
21
|
+
include Yogo::DataMapper::Model::Configuration
|
22
|
+
|
23
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
24
|
+
property :name, String, :required => true
|
25
|
+
|
26
|
+
has n, :model_operations
|
27
|
+
|
28
|
+
def operation_definitions
|
29
|
+
model_operations.map{|model_op| model_op.to_a }
|
30
|
+
end
|
31
|
+
|
32
|
+
def update(model=nil)
|
33
|
+
to_proc.call(model || (@_model ||= DataMapper::Model.new))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ModelOperation
|
38
|
+
include DataMapper::Resource
|
39
|
+
|
40
|
+
Yogo::DataMapper::Model::Common::Properties::UUIDKey[self]
|
41
|
+
|
42
|
+
property :operation, String, :required => true
|
43
|
+
property :parameters, Yaml, :default => lambda{|*args| [] }
|
44
|
+
|
45
|
+
def to_a
|
46
|
+
[self.operation, self.parameters].flatten
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'yogo/datamapper/dynamic/stored/configuration'
|
2
|
+
|
3
|
+
|
4
|
+
class ProjectRemix
|
5
|
+
include ::DataMapper::Resource
|
6
|
+
|
7
|
+
property :id, UUID, :key => true, :default => lambda { Yogo::Configuration.random_uuid }
|
8
|
+
property :name, String, :required => true
|
9
|
+
|
10
|
+
without_auto_validations do
|
11
|
+
remix n, 'Yogo::DataMapper::Dynamic::Stored::Configuration', :as => :model_configurations, :model => 'ProjectModelConfiguration'
|
12
|
+
enhance :configuration do
|
13
|
+
property :project_id, UUID
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end # ProjectRemix
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Yogo Data Management Toolkit
|
2
|
+
# Copyright (c) 2010 Montana State University
|
3
|
+
#
|
4
|
+
# License -> see license.txt
|
5
|
+
#
|
6
|
+
# FILE: data_stream.rb
|
7
|
+
# The Data Stream model is where the streaming data parsing templates are stores.
|
8
|
+
#
|
9
|
+
|
10
|
+
# Class for a Yogo Project. A project contains a name, a description, and access to all of the models
|
11
|
+
# that are part of the project.
|
12
|
+
module Yogo
|
13
|
+
module Voeis
|
14
|
+
module Managed
|
15
|
+
class DataStream
|
16
|
+
include ::DataMapper::Resource
|
17
|
+
|
18
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
19
|
+
|
20
|
+
property :name, String, :required => true, :unique => true
|
21
|
+
property :description, Text, :required => false
|
22
|
+
property :filename, String, :required => true, :length => 512
|
23
|
+
property :start_line, Integer, :required => true, :default => 0
|
24
|
+
|
25
|
+
property :project_id, Integer, :required =>true, :default => 1
|
26
|
+
|
27
|
+
validates_uniqueness_of :name
|
28
|
+
|
29
|
+
#before :destroy, :delete_data_stream_columns!
|
30
|
+
|
31
|
+
has n, :sites, :through => Resource
|
32
|
+
# has n, :data_stream_columns, :model => "DataStreamColumn", :through => Resource
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
end # DataStream
|
37
|
+
end # Managed
|
38
|
+
end # Voeis
|
39
|
+
end # Yogo
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Sites TODO- validate the best practices below
|
2
|
+
#
|
3
|
+
# This is a "Monitoring Site Locations"
|
4
|
+
# The Sites table provides information giving the spatial location at which data values have been
|
5
|
+
# collected.
|
6
|
+
# The following rules and best practices should be followed when populating this table:
|
7
|
+
# * The SiteID field is the primary key, must be a unique integer, and cannot be NULL. This
|
8
|
+
# field should be implemented as an auto number/identity field.
|
9
|
+
# * The SiteCode field must contain a text code that uniquely identifies each site. The values
|
10
|
+
# in this field should be unique and can be an alternate key for the table. SiteCodes cannot
|
11
|
+
# contain any characters other than A-Z (case insensitive), 0-9, period “.”, dash “-“, and
|
12
|
+
# underscore “_”.
|
13
|
+
# * The LatLongDatumID must reference a valid SpatialReferenceID from the
|
14
|
+
# SpatialReferences controlled vocabulary table. If the datum is unknown, a default value
|
15
|
+
# of 0 is used.
|
16
|
+
# * If the Elevation_m field is populated with a numeric value, a value must be specified in
|
17
|
+
# the VerticalDatum field. The VerticalDatum field can only be populated using terms
|
18
|
+
# from the VerticalDatumCV table. If the vertical datum is unknown, a value of
|
19
|
+
# “Unknown” is used.
|
20
|
+
# * If the LocalX and LocalY fields are populated with numeric values, a value must be
|
21
|
+
# specified in the LocalProjectionID field. The LocalProjectionID must reference a valid
|
22
|
+
# SpatialReferenceID from the SpatialReferences controlled vocabulary table. If the spatial
|
23
|
+
# reference system of the local coordinates is unknown, a default value of 0 is used.
|
24
|
+
#
|
25
|
+
module Yogo
|
26
|
+
module Voeis
|
27
|
+
module Managed
|
28
|
+
class Site
|
29
|
+
include ::DataMapper::Resource
|
30
|
+
|
31
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
32
|
+
property :site_code, String, :required => true
|
33
|
+
property :site_name, String, :required => true
|
34
|
+
property :latitude, Float, :required => true
|
35
|
+
property :longitude, Float, :required => true
|
36
|
+
property :lat_long_datum_id, Integer, :required => true, :default => 0
|
37
|
+
property :elevation_m, Float, :required => false
|
38
|
+
property :vertical_datum, String, :required => false
|
39
|
+
property :local_x, Float, :required => false
|
40
|
+
property :local_y, Float, :required => false
|
41
|
+
property :local_projection_id, Integer, :required => false
|
42
|
+
property :pos_accuracy_m, Float, :required => false
|
43
|
+
property :state, String, :required => false
|
44
|
+
property :country, String, :required => false
|
45
|
+
property :comments, String, :required => false
|
46
|
+
|
47
|
+
has n, :data_streams, :through => Resource
|
48
|
+
end # Site
|
49
|
+
end # Managed
|
50
|
+
end # Voeis
|
51
|
+
end # Yogo
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-types/uuid'
|
3
|
+
|
4
|
+
require 'yogo/datamapper/repository_manager'
|
5
|
+
require 'yogo/example/voeis/managed/site'
|
6
|
+
require 'yogo/example/voeis/managed/data_stream'
|
7
|
+
|
8
|
+
module Yogo
|
9
|
+
module Voeis
|
10
|
+
class Project
|
11
|
+
include ::DataMapper::Resource
|
12
|
+
include Yogo::DataMapper::RepositoryManager
|
13
|
+
|
14
|
+
property :id, UUID, :key => true, :default => lambda { UUIDTools::UUID.timestamp_create }
|
15
|
+
property :name, String, :required => true
|
16
|
+
property :description, String
|
17
|
+
|
18
|
+
def self.manage(klass)
|
19
|
+
@managed_models ||= []
|
20
|
+
unless @managed_models.include?(klass)
|
21
|
+
@managed_models << klass
|
22
|
+
end
|
23
|
+
@managed_models
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.managed_models
|
27
|
+
@managed_models
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def managed_repository_name
|
32
|
+
ActiveSupport::Inflector.tableize(id.to_s).to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
def adapter_config
|
36
|
+
{
|
37
|
+
:adapter => 'sqlite',
|
38
|
+
:database => "voeis-project-#{managed_repository_name}.db"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare_models
|
43
|
+
adapter # ensure the adapter exists or is setup
|
44
|
+
managed_repository.scope {
|
45
|
+
self.class.managed_models.each do |klass|
|
46
|
+
klass.auto_upgrade!
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
after :save, :prepare_models
|
52
|
+
|
53
|
+
manage Managed::Site
|
54
|
+
manage Managed::DataStream
|
55
|
+
end # Project
|
56
|
+
end # Voeis
|
57
|
+
end # Yogo
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'facets/proc/curry'
|
2
|
+
require 'facets/proc/compose'
|
3
|
+
|
4
|
+
X = :partial_unspecified_argument
|
5
|
+
|
6
|
+
module Yogo
|
7
|
+
class Operation < Proc
|
8
|
+
|
9
|
+
def self.on(type, &block)
|
10
|
+
op = self.new(&block)
|
11
|
+
op.instance_eval{ self.type = type }
|
12
|
+
op
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(*args)
|
16
|
+
x = args.first
|
17
|
+
raise "Can only invoke on #{type}" if type && !x.is_a?(type)
|
18
|
+
super(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
private
|
24
|
+
attr_accessor :type
|
25
|
+
end # Operation
|
26
|
+
|
27
|
+
class ::Proc
|
28
|
+
def partial(*args)
|
29
|
+
Proc.new do |*spice|
|
30
|
+
result = args.collect do |a|
|
31
|
+
X == a ? spice.shift : a
|
32
|
+
end
|
33
|
+
call(*result)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Operations
|
39
|
+
def self.[](op_name)
|
40
|
+
op_name.split("::").reduce(self) do |namespace, const|
|
41
|
+
if namespace && namespace.const_defined?(const)
|
42
|
+
namespace.const_get(const)
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # Yogo
|
data/lib/yogo/project.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-types/uuid'
|
3
|
+
require 'yogo/collection'
|
4
|
+
|
5
|
+
module Yogo
|
6
|
+
class Project
|
7
|
+
include ::DataMapper::Resource
|
8
|
+
|
9
|
+
property :id, UUID, :key => true, :default => lambda { |p,r| UUIDTools::UUID.timestamp_create }
|
10
|
+
property :name, String, :required => true
|
11
|
+
property :description, Text
|
12
|
+
|
13
|
+
has n, :data_collections, :model => 'Yogo::Collection::Data', :child_key => [:project_id]
|
14
|
+
|
15
|
+
chainable do
|
16
|
+
def as_json(options={})
|
17
|
+
{
|
18
|
+
:id => self.id.to_s,
|
19
|
+
:name => self.name,
|
20
|
+
:description => self.description,
|
21
|
+
:data_collections => self.data_collections.map{|c| c.id.to_s }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_attributes(hash)
|
26
|
+
attrs = {}
|
27
|
+
attrs[:name] = hash[:name] || hash['name'] || self.name
|
28
|
+
attrs[:description] = hash[:description] || hash['description'] || self.description
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end # Project
|
32
|
+
end # Yogo
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
Example of an asset.
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Standard requirements for Bundler management
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
# Load the bundler gemset
|
6
|
+
Bundler.setup(:default, ENV['RACK_ENV'] || :test )
|
7
|
+
|
8
|
+
# Mess with load paths
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
10
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
+
|
12
|
+
require 'rspec/core'
|
13
|
+
require 'autotest/rspec2'
|
14
|
+
require 'rack/test'
|
15
|
+
require 'rack/mock'
|
16
|
+
|
17
|
+
require 'data_mapper'
|
18
|
+
require 'dm-postgres-adapter'
|
19
|
+
require 'dm-sqlite-adapter'
|
20
|
+
|
21
|
+
require 'yogo-project'
|
22
|
+
|
23
|
+
require 'yogo/project'
|
24
|
+
require 'yogo/collection'
|
25
|
+
|
26
|
+
Dir[File.join(File.dirname(__FILE__), "helpers", "**/*.rb")].each do |f|
|
27
|
+
require f
|
28
|
+
end
|
29
|
+
|
30
|
+
Dir[File.join(File.dirname(__FILE__), "factories", "**/*.rb")].each do |f|
|
31
|
+
require f
|
32
|
+
end
|
33
|
+
|
34
|
+
SPEC_DIR = File.expand_path(File.dirname(__FILE__))
|
35
|
+
SPEC_TMP_DIR = File.join(SPEC_DIR, 'tmp')
|
36
|
+
SPEC_RES_DIR = File.join(SPEC_DIR, 'resource')
|
37
|
+
|
38
|
+
DB_URL = "sqlite://#{SPEC_TMP_DIR}/projects.db"
|
39
|
+
COLLECTION_URL = "sqlite://#{SPEC_TMP_DIR}/collections.db"
|
40
|
+
|
41
|
+
Rspec.configure do |config|
|
42
|
+
config.before(:suite) do
|
43
|
+
DataMapper::Model.raise_on_save_failure = true
|
44
|
+
DataMapper::Logger.new('log/datamapper.log', :debug)
|
45
|
+
@default = ::DataMapper.setup(:default, DB_URL)
|
46
|
+
@collection_data = ::DataMapper.setup(:collection_data, COLLECTION_URL)
|
47
|
+
::DataMapper.finalize.auto_migrate!
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collection Data Models" do
|
4
|
+
it "should be a datamapper model" do
|
5
|
+
@data_model.should be_a_kind_of(::DataMapper::Model)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should use the collection data_repository" do
|
9
|
+
@collection.scope do
|
10
|
+
@data_model.repository.should == @data_model.collection.collection_repository
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "core properties" do
|
16
|
+
it "should include :id" do
|
17
|
+
@collection.scope do
|
18
|
+
@data_model.properties[:id].should_not be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should include :created_at" do
|
23
|
+
@collection.scope do
|
24
|
+
@data_model.properties[:created_at].should_not be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should include :updated_at" do
|
29
|
+
@collection.scope do
|
30
|
+
@data_model.properties[:updated_at].should_not be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collection Managers" do
|
4
|
+
|
5
|
+
describe "class" do
|
6
|
+
before(:each) do
|
7
|
+
@manager_class = @manager.class
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be a datamapper model" do
|
11
|
+
@manager_class.should be_a_kind_of(::DataMapper::Model)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a repository for collections"
|
16
|
+
it "should have collections"
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
shared_examples_for "All Collections" do
|
4
|
+
it "should have a name" do
|
5
|
+
@collection.name.should be_a_kind_of(String)
|
6
|
+
@collection.name.should_not be_empty
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should allow name to be changed" do
|
10
|
+
new_name = "Cercal Cell DB"
|
11
|
+
|
12
|
+
@collection.name = new_name
|
13
|
+
@collection.should be_valid
|
14
|
+
@collection.save.should be_true
|
15
|
+
@collection.name.should == new_name
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow description to be changed" do
|
19
|
+
new_description = "Example Database"
|
20
|
+
@collection.description = new_description
|
21
|
+
@collection.should be_valid
|
22
|
+
@collection.save.should be_true
|
23
|
+
@collection.description.should == new_description
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
it "should have a collection_repository" do
|
28
|
+
@collection.should respond_to(:collection_repository)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "collection_repository" do
|
32
|
+
it "should be a datamapper respository" do
|
33
|
+
@collection.collection_repository.should be_a_kind_of(DataMapper::Repository)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have a data_model" do
|
38
|
+
@collection.should respond_to(:data_model)
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "data_model" do
|
42
|
+
before(:each) do
|
43
|
+
@data_model = @collection.data_model
|
44
|
+
end
|
45
|
+
|
46
|
+
it_should_behave_like "All Collection Data Models"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have items" do
|
50
|
+
@collection.should respond_to(:items)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|